package com.example.commom.util.remote;

import com.alibaba.fastjson.JSON;
import com.example.commom.exception.BizException;
import com.example.commom.model.ApiResult;
import lombok.extern.slf4j.Slf4j;

/**
 * 包含事物回滚的远程调用链
 */
@Slf4j
public class TransactionalRemoteTransferChain extends AbstractRemoteTransferChain {

    @Override
    public void execute() {
        for (int i = 0; i < remoteProperties.size(); i++) {
            RemoteProperties remotePro =remoteProperties.get(i);
            // 起始节点
            if (i == 0) {
                transferHandler(i, remotePro);
            } else {
                // 判断是否需要前置任务
                if (remotePro.isPreRequired()) {
                    transferCallbackHandler(i, remotePro);
                } else {
                    transferHandler(i, remotePro);
                }
            }
        }
    }

    private void transferHandler(int i, RemoteProperties remotePro) {
        RemoteTransferHandler remoteTransferHandler = remotePro.getRemoteTransferHandler();
        try {
            ApiResult<?> apiResult = remoteTransferHandler.call();
            if (null == apiResult) {
                return;
            }
            if (apiResult.getErrorCode().equals("000000")) {
                rollback(i);
                return;
            }
            if (null != apiResult.getData()) {
                remotePro.setResult(JSON.toJSONString(apiResult.getData()));
            }
        } catch (Exception e) {
            log.error("call error", e);
            rollback(i);
        }
    }


    private void transferCallbackHandler(int i, RemoteProperties remotePro) {
        RemoteTransferCallbackHandler remoteTransferCallbackHandler = remotePro.getRemoteTransferCallbackHandler();
        try {
            if (remotePro.getResultIndex() < 0) {
                throw new BizException("无结果节点");
            }
            ApiResult<?> apiResult = remoteTransferCallbackHandler.call(remoteProperties.get(remotePro.getResultIndex()).getResult());
            if (null == apiResult) {
                return;
            }
            if (!apiResult.getErrorCode().equals("000000")) {
                rollback(i);
                return;
            }
            if (null != apiResult.getData()) {
                remotePro.setResult(JSON.toJSONString(apiResult.getData()));
            }
        } catch (Exception e) {
            log.error("call error", e);
            rollback(i);
        }
    }
}
